TITLE MASM Template						(main.asm)

; Description:
; 
; Revision date:

INCLUDE Irvine32.inc
.data

;OPR I P ADDRESS

;Memory is split into pages of 127 bytes (12-bit)
;When the page bit is set, it will take whichever page you're in (AND the program counter with 1111111110000000)
;and add the amount in the curAddress
;When the page bit is not set, it will just use curAddress! In other words, adding to 0
;  0-127 128-255 256-etc.
;            ^-------000 10 1100100
;  0-127 128-255 256-etc.
;     ^--------------000 00 1100100
;
;When the indirect bit is set, it looks at the value acquired with the page bit stuff
;It uses the entire 12 bits of that to refer to an absolute location in memory
;
;JMS stores a 12-bit return address at the address pointed to
;Returning is done by doing an indirect jump to the address value at the JMS command

;101 10 0000011 0: JMP indirect location 3
;011 00 0000110	1: DCA location 6
;101 00 0000111	2: JMP location 7
;000 01 0000000	3: Data 128
;000 00 0011110	4: Data 30
;000 00 0101000	5: Data 40
;000 00 0000000	6: Data 0 (8 goes here)
;010 00 0001000	7: ISZ location 8
;111 11 1111111	8: Data MAXIMUM OVERDRIVE
;101 00 0000001	9: JMP location 1
;-----------------
;001 01 0000100	128: TAD page location 4
;001 00 0000100	129: TAD absolute location 4
;000 11 0000101	130: AND page indirect location 5
;100 00 0000000 131: JMS absolute location 0 (should overwrite the JMP)
;000 00 0010100 132: Data 20
;000 00 0000101 133: Data 5
memory WORD 0000101100000011b, 0000011000000110b, 0000101000000111b, 0000000010000000b, 0000000000011110b, 0000000010101000b, 0000000000000000b, 0000010000001000b, 0000111111111111b, 0000101000000001b
someBlankSpace WORD 118 DUP(0)	;Fill the rest of the page
secondPage WORD 0000001010000100b, 0000001000000100b, 0000000110000101b, 0000100000000000b, 0000000000010100b, 0000000000000101b
curAddress WORD 0h
nextInstruction DWORD 0h
accumulator WORD 0h
swapSpace DWORD 0h

.code
getAddressAndStore PROC ;Gets an address at location edx, stores into curAddress
	mov ax, [edx]				;Location edx is now in ax
	and ax, 0000000001111111b	;Isolated 7 address bits
	mov curAddress, ax			;Stored!
	
	ret
getAddressAndStore ENDP

getInstructionAndPerform PROC	;Gets an instruction at location edx, checks it and performs the operation
	mov ax, [edx]				;Location edx is now in ax
	and ax, 0000111000000000b	;Isolated 3-bit instruction
	
	cmp ax, 0000000000000000b	;Check for AND
	jne notAnd					;---AND INSTRUCTIONS BEGIN HERE---
	
	mov edx, OFFSET memory		;Sets first location in virtual memory
	add dx, curAddress			;Add the address offset
	add dx, curAddress			;Twice 'cuz of word
	mov ax, [edx]				;The value in curAddress is now in ax
	and accumulator, ax			;AND the value in ax with the virtual accumulator
	mov edx, nextInstruction	;Reset edx
	jmp done					;Jump down to skip the rest of the comparisons
	
	notAnd:
	cmp ax, 0000001000000000b	;Check for TAD
	jne notTad					;---TAD INSTRUCTIONS BEGIN HERE---
	
	mov edx, OFFSET memory		;Sets first location in virtual memory
	add dx, curAddress			;Add the address offset
	add dx, curAddress			;Twice 'cuz of word
	mov ax, [edx]				;The value in curAddress is now in ax
	add accumulator, ax			;And the value in ax is now added to the virtual accumulator
	mov edx, nextInstruction	;Reset edx
	jmp done					;Jump down to skip the rest of the comparisons
	
	notTad:
	cmp ax, 0000011000000000b	;Check for DCA
	jne notDca					;---DCA INSTRUCTIONS BEGIN HERE---

	mov edx, OFFSET memory		;Sets first location in virtual memory
	add dx, curAddress			;Add the address offset
	add dx, curAddress			;Twice 'cuz of word
	mov ax, accumulator			;Put the contents of virtual accumulator into ax
	mov [edx], ax				;And deposit the virtual accumulator into the memory location specified in the address
	mov edx, nextInstruction	;Reset edx
	jmp done					;Jump down to skip the rest of the comparisons

	notDca:
	cmp ax, 0000101000000000b	;Check for JMP
	jne notJmp					;---JMP INSTRUCTIONS BEGIN HERE---
	
	mov edx, OFFSET memory		;Sets first location in virtual memory
	add dx, curAddress			;Add the address offset
	add dx, curAddress			;...and don't reset edx because we want to jump here
	dec edx						;Do this twice to compensate for adds in main proc (pretty bad practice!)
	dec edx
	jmp done					;Jump down to skip the rest of the comparisons
	
	notJmp:
	cmp ax, 0000010000000000b	;Check for ISZ
	jne notIsz					;---ISZ INSTRUCTIONS BEGIN HERE---
	
	mov edx, OFFSET memory		;Sets first location in virtual memory
	add dx, curAddress			;Add the address offset
	add dx, curAddress			;Twice 'cuz of word
	mov ax, [edx]				;The value in curAddress is now in ax
	inc ax						;The incrementing part of ISZ!
	mov [edx], ax				;Incrementing it in virtual memory
	and ax, 0000111111111111b	;Getting rid of the 4 bits that aren't in PDP-8 memory
	mov edx, nextInstruction	;Reset edx early 
	cmp ax, 0000000000000000b	;The seeing if it's 0 part of ISZ...
	jne iszNotZero				;...skip this next part if it isn't
	inc edx						;Skip an instruction if it was zero
	inc edx
	iszNotZero:
	jmp done					;Jump down to skip the rest of the comparisons
	
	notIsz:
	cmp ax, 0000100000000000b	;Check for JMS
	jne notJms					;---JMS INSTRUCTIONS BEGIN HERE---
	
	mov edx, OFFSET memory		;Sets first location in virtual memory
	mov swapSpace, edx			;Put it in our temporary space so we can do math with it
	mov edx, nextInstruction	;Get our current instruction location in real memory	
	sub edx, swapSpace			;Subtract the first location in virtual memory - now we have the virtual memory address in dx
	shr edx, 1					;Just like how we've been adding twice, now we need to divide by 2 to get the right address
	inc edx						;And increment it so it points to the instruction after this one that it's performing
	mov swapSpace, edx			;Put it in the temporary space
	mov edx, OFFSET memory		;Set first location in virtual memory for the jump part now
	add dx, curAddress			;Add the address offset
	add dx, curAddress			;...and don't reset edx because we want to jump here
	mov eax, swapSpace
	mov [edx], ax				;Put the old address in the first location and let the program counter increment to skip it
	
	jmp done					;Jump down to skip the rest of the comparisons
	
	notJms:
	done:
	ret
getInstructionAndPerform ENDP

checkIndirect PROC
	mov ax, [edx]				;Location edx is now in ax
	and ax, 0000000100000000b	;Isolated indirect bit
	
	cmp ax, 0000000100000000b	;Check for indirect bit
	jne noIndirect
	
	mov edx, OFFSET memory		;Set first location in virtual memory
	add dx, curAddress			;Add the old address to that
	add dx, curAddress
	mov ax, [edx]				;Look at the 12 bits in there
	mov curAddress, ax			;The entire thing becomes our new address
	
	noIndirect:
	ret
checkIndirect ENDP

checkPage PROC
	mov ax, [edx]				;Location edx is now in ax
	and ax, 0000000010000000b	;Isolated page bit
	
	cmp ax, 0000000010000000b	;Check for page bit
	jne noPage
	
	mov edx, nextInstruction
	and dx, 0000111110000000b
	shr dx, 1
	add curAddress, dx
	
	noPage:
	ret
checkPage ENDP
	
main PROC
	mov edx, OFFSET memory		;Sets first location in virtual memory
do:
	mov nextInstruction, edx
	call getAddressAndStore
	call checkPage
	mov edx, nextInstruction
	call checkIndirect
	mov edx, nextInstruction
	call getInstructionAndPerform
	inc edx						;Next instruction
	inc edx						;Needs to do twice 'cuz of word!
	
	jmp do

	exit
main ENDP

END main